package org.gitman.agentplatform.ui.graph;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import org.gitman.agentplatform.ui.MainFrame;
import org.gitman.agentplatform.ui.actions.ActionsManager;
import org.gitman.agentplatform.ui.api.View;
import org.gitman.agentplatform.ui.api.View.MessageType;

import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.view.mxGraph;

public class GraphPanel extends JPanel {
	
	private MainFrame mainFrame;
	private JTextField numVert;
	private JTextField minEdgeNum;
	private JTextField maxEdgeNum;
	private JSlider slider;
	private JComboBox comboEdge;
	private JComboBox comboVert;
	private ActionsManager actionsManager;
	private static String editDescription = 
			"<html>" +
			"To edit graph follow instructions:" +
			"<ul>" +
			"<li> Create new Graph or open from file"+
			"<li> Select \"Start Editing\" to begin"+
			"<li> To add vertex double click mouse LB"+
			"<li> To add edge press down LB over vertex and drag new edge to another verex"+
			"<li> You can also drag vertex and drop it on edge to pin it to this edge" +
			"<li> To delete edge or vertex click on it mouse RB" +
			"<li> At the end click \"Finish Editing\" button" +
			"</ul>" +
			"</html>";
		
	public GraphPanel(final MainFrame mainFrame) {
		this.mainFrame = mainFrame;
		actionsManager = mainFrame.getActionsManager();
		
		setLayout(new BorderLayout());
		
		JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
		buttonPanel.add(new JButton(actionsManager.startEditingAction));
		buttonPanel.add(new JButton(actionsManager.finishEditingAction));
		add(buttonPanel, BorderLayout.NORTH);
		
		JPanel p1 = new JPanel(new BorderLayout());
		add(p1, BorderLayout.CENTER);
		
		JPanel editPanel = new JPanel(new BorderLayout());
		editPanel.setBorder(BorderFactory.createTitledBorder("Edit Graph"));
		editPanel.add(new JLabel(editDescription));
		p1.add(editPanel, BorderLayout.NORTH);
		
		JPanel p2 = new JPanel(new BorderLayout());
		p1.add(p2, BorderLayout.CENTER);
		
		JPanel genertaionPanel = new JPanel(new GridLayout(11,1));
		genertaionPanel.setBorder(BorderFactory.createTitledBorder("Generate Graph"));
		JPanel vertexPanel = new JPanel(new GridLayout(1,2));
		vertexPanel.add(new JLabel("Number of vertices"));
		numVert = new JTextField(6);
		numVert.setText("35");
		vertexPanel.add(numVert);
		vertexPanel.setToolTipText("Number of vertices to be generated for graph");
		genertaionPanel.add(vertexPanel);
		JPanel minEdgePanel = new JPanel(new GridLayout(1,2));
		minEdgePanel.add(new JLabel("Min. number of E/V"));
		minEdgeNum = new JTextField(6);
		minEdgeNum.setText("1");
		minEdgePanel.add(minEdgeNum);
		minEdgePanel.setToolTipText("Minimum number of edges outgoing from each vertex");
		genertaionPanel.add(minEdgePanel);
		JPanel maxEdgePanel = new JPanel(new GridLayout(1,2));
		maxEdgePanel.add(new JLabel("Max. number of E/V"));
		maxEdgeNum = new JTextField(6);
		maxEdgeNum.setText("6");
		maxEdgePanel.add(maxEdgeNum);
		maxEdgePanel.setToolTipText("Maximum number of edges outgoing from each vertex");
		genertaionPanel.add(maxEdgePanel);
		JPanel aboveSlider = new JPanel(new FlowLayout());
		aboveSlider.add(new JLabel("Select level of randomnes:"));
		genertaionPanel.add(aboveSlider);
		JPanel sliderPanel = new JPanel(new BorderLayout());
		slider = new JSlider(SwingConstants.HORIZONTAL, 0, 100, 20);
		sliderPanel.add(slider);
		genertaionPanel.add(sliderPanel);
		JPanel underSlider = new JPanel(new BorderLayout());
		underSlider.add(new JLabel("Neighbors"), BorderLayout.WEST);
		underSlider.add(new JLabel("Random"), BorderLayout.EAST);
		genertaionPanel.add(underSlider);
		JPanel generationTypePanel = new JPanel(new GridLayout(1,2));
		generationTypePanel.add(new JLabel("Method generating edges:"));
		comboEdge = new JComboBox(Method2GenerateEdges.values());
		generationTypePanel.add(comboEdge);
		generationTypePanel.setToolTipText("<html>This method indicate how edges should be added to graph:<ul><li>Random - all edges are added randomly<li>Neighbors - each vertex is connected to selected number of neighbors<li>Mixed - combains both above methods, where Random get selected % of edges</ul></html>");
		genertaionPanel.add(generationTypePanel);
		JPanel vertGenPanel = new JPanel(new GridLayout(1,2));
		vertGenPanel.add(new JLabel("Method generating vertices:"));
		comboVert = new JComboBox(Method2GenerateVertices.values());
		vertGenPanel.add(comboVert);
		vertGenPanel.setToolTipText("<html>This method indicate how to arrange vertices on display:<ul><li>Random - vertices are randomly putted on dipslay<li>Grid - vertices are putted into generated gird</ul></html>");
		genertaionPanel.add(vertGenPanel);
		genertaionPanel.add(new JButton(actionsManager.generateGraphAction));
		genertaionPanel.add(new JButton(actionsManager.autoLayoutAction));
		genertaionPanel.add(new JButton(actionsManager.bothWayEdgesAction));
		p2.add(genertaionPanel, BorderLayout.NORTH);		
	}

	public void generateGraph(){
		try {				
			int v = Integer.parseInt(numVert.getText());
			int minE = Integer.parseInt(minEdgeNum.getText());
			int maxE = Integer.parseInt(maxEdgeNum.getText());
			int randP = slider.getValue();
			Method2GenerateEdges meth = (Method2GenerateEdges) comboEdge.getSelectedItem();
			Method2GenerateVertices methV = (Method2GenerateVertices) comboVert.getSelectedItem();
			GraphEditor.getInstance().generateGraph(v,minE,maxE, randP, meth, methV);
		} catch (Exception e) {
			View.showMessage(e.getMessage(), MessageType.ERROR);
			e.printStackTrace();
		}
	}

	public void fitGraphOnScreen(mxGraph graph){
		GraphDisplPanel graphDisplPanel = mainFrame.getGraphDisplPanel();
		Object[] childVertices = graph.getChildVertices(graph.getDefaultParent());
		if(childVertices.length > 1){
			int SIZE = graphDisplPanel.getDotSize();
			int width = graphDisplPanel.getWidth() - 2*SIZE;
			int height = graphDisplPanel.getHeight() - 2*SIZE;
			int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, 
					maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
			for(Object o : childVertices){
				mxCell cell = (mxCell) o;
				mxGeometry geometry = cell.getGeometry();
				int x = geometry.getPoint().x;
				int y = geometry.getPoint().y;
				if(minX > x){
					minX =x;
				}
				if(maxX < x){
					maxX = x;
				}
				if(minY > y){
					minY = y;
				}
				if(maxY < y){
					maxY = y;
				}
			}
			int graphWidth = maxX - minX + SIZE;
			int graphHeight = maxY - minY + SIZE;
			double xScale = ((double)(width*1.0))/((double)(graphWidth*1.0));
			double yScale = ((double)(height*1.0))/((double)(graphHeight*1.0));
			
			graph.getModel().beginUpdate();
			try{
				for(Object o : childVertices){
					mxCell cell = (mxCell) o;
					cell.getGeometry().translate(-minX,-minY);
					double xx =cell.getGeometry().getCenterX();
					double yy= cell.getGeometry().getCenterY();
					cell.getGeometry().translate(-xx + xx*xScale + SIZE, -yy + yy*yScale + SIZE);
				}
			}finally{
				graph.getModel().endUpdate();
			}		
			graph.refresh();
		}
	}


}
